package pATT.bNEdit.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import pATT.bNEdit.base.Nodo;
import pATT.bNEdit.base.RedBayes;
import pATT.bNEdit.obj17.BarViewNodo;
import pATT.bNEdit.obj17.ProbView;
import pATT.bNEdit.obj17.View;



/**
* <p>Title: BNEdit</p>
* <p>Description: Bayesian Network Editor</p>
* <p>Copyright: Copyright (c) 2005</p>
* <p>Company: </p>
* @author Luciana Zavaleta
* @version 1.0
*/

public class RunPanel extends JPanel{
  /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
private RedBayes bayesianNetwork = null;
  private Font infoFont=new java.awt.Font("Arial", Font.PLAIN, 13);
  private BNEditInternalFrame internalFrame;

  JPanel grafBarras = new JPanel();
  JPanel query = new JPanel();
  JPanel info = new JPanel();

  JScrollPane scrollPane = new JScrollPane();

  JButton bDelete = new JButton("Delete");
  JButton bAceptar = new JButton("Evidence");

  JComboBox jVar, jEstado, jObser;

  JLabel varLabel, estadoLabel, infoLabel, varObsLabel, probLabel;




  public RunPanel() {
    try {
      jbInit();
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
    Component[] components = this.getComponents();
    for (int i = 0; i < components.length; i++) {
      components[i].setEnabled(false);
    }
  }

  void jbInit() throws Exception {

    this.setLayout(new BorderLayout());
    this.setBorder(BorderFactory.createLineBorder(Color.black));
    this.setPreferredSize(new Dimension(250, 170));
    this.add(info, BorderLayout.NORTH);
    this.add(scrollPane, BorderLayout.CENTER);
    this.add(query, BorderLayout.SOUTH);

    grafBarras.setLayout(new FlowLayout(FlowLayout.LEFT));
    grafBarras.setAutoscrolls(true);
    grafBarras.setPreferredSize(new Dimension(250, 500));

    varLabel = new JLabel("Variable name:");
    estadoLabel = new JLabel("Estate:");
    varObsLabel = new JLabel("Evidences:");

    jVar = new JComboBox();
    jEstado = new JComboBox();
    jObser = new JComboBox();
    infoLabel = new JLabel();
    probLabel=new JLabel();

    jVar.addItemListener(new RunPanel_jVar_itemAdapter(this));
    bAceptar.setToolTipText("Add observation");
    bAceptar.addActionListener(new RunPanel_bAceptar_actionAdapter(this));

    bDelete.setToolTipText("Delete observation");
    bDelete.addActionListener(new RunPanel_bDelete_actionAdapter(this));

    query.setLayout(new FlowLayout());
    query.add(varLabel);
    query.add(jVar);
    query.add(estadoLabel);
    query.add(jEstado);
    query.add(bAceptar);
    query.add(varObsLabel);
    query.add(jObser);
    query.add(bDelete);

    info.add(infoLabel);
    info.add(probLabel);

    infoLabel.setFont(infoFont);
    probLabel.setFont(infoFont);

    scrollPane.setBorder(BorderFactory.createLineBorder(Color.black));
    scrollPane.setPreferredSize(new Dimension(250, 170));
    scrollPane.getViewport().add(grafBarras, null);

  }

  public void setInternalFrame (BNEditInternalFrame internal){
    internalFrame=internal;
  }


  /**
   * this method is called every time the user changes to Run type
   */
  public void SetComponents(){
    for (Enumeration e=bayesianNetwork.ListaNodos().elements();
e.hasMoreElements();){
      addView((Nodo) e.nextElement());
    }

    if (jVar.getItemCount()!=0){
      jVarChanged((String) jVar.getSelectedItem());
    }



    infoLabel.setText("Network initialized (All evidence retracted)");
    probLabel.setText("");
  }

  public void removeComponents(){
    this.reinicializar();
    grafBarras.removeAll();
    jVar.removeAllItems();
    jEstado.removeAllItems();
  }

  /**
   * Adds a bar graphic for the given node
   * @param node
   * @return the vertex's View
   */
   private void addView(Nodo node){
     View bv=new BarViewNodo(node, bayesianNetwork);
     bv.addMouseListener(new RunPanel_this_mouseAdapter(this));
     grafBarras.add(bv);
     jVar.addItem(bayesianNetwork.NombreExt(node));
   }

   public View getView(String name){
     Component[] graf=grafBarras.getComponents();
     for (int i=0; i<graf.length;i++){
       if (((View) graf[i]).getTitle().equals(name))
         return (View) graf[i];
     }
     return null;
   }

  @SuppressWarnings("unused")
private Nodo getNodo(String varName){
   for (Enumeration
e=bayesianNetwork.ListaNodos().elements();e.hasMoreElements();){
      Nodo actual=(Nodo) e.nextElement();
      if (bayesianNetwork.NombreExt(actual).equals((String)varName))
        return actual;
    }
   return null;
  }



  /**
   * setBayesianNetwork
   * @param bayesianNetwork RedBayes
   */
  public void setBayesianNetwork(RedBayes bayesianNetwork) {
    this.bayesianNetwork = bayesianNetwork;

  }

  /**
   * Shows the given propagation probabilities
   * @param form - the propagation probabilities's name
   */
  public void showForm (String form) {
    Component[] vistas= grafBarras.getComponents();
    //if there is any node
    if (vistas.length!=0) {
      Class c = null;
      try {
        c = Class.forName(form);
      }
      catch (ClassNotFoundException ex) {
      }
      //if the new propagation form is different from the actual propagation form
      if ( ( (BarViewNodo) vistas[0]).getProbView().getClass() != c) {
        Class first = null;
        try {
          first = Class.forName("edu.unicen.bayes.base.RedBayes");
        }
        catch (ClassNotFoundException ex1) {
        }
        Class second = null;
        try {
          second = Class.forName("edu.unicen.bayes.base.Nodo");
        }
        catch (ClassNotFoundException ex2) {
        }
        Class[] parameters = {first, second};
        Constructor ct = null;
        try {
          ct = c.getConstructor(parameters);
        }
        catch (SecurityException ex3) {
        }
        catch (NoSuchMethodException ex3) {
        }
        //Changes all graphics
        for (int i=0; i<vistas.length;i++){
          BarViewNodo bv= (BarViewNodo) vistas[i];
          Object[] valors = {bayesianNetwork, (Nodo)bv.getSubject()};
          try {
            bv.changeProbView( (ProbView) ct.newInstance(valors));
          }
          catch (InvocationTargetException ex4) {
          }
          catch (IllegalArgumentException ex4) {
          }
          catch (IllegalAccessException ex4) {
          }
          catch (InstantiationException ex4) {
          }

        }
        //shows the new probability
        probLabel.setText( (new Double(getProb())).toString());

        this.updateUI();
      }
    }
  }

  /**
   * Shows the given node's states
   * @param varName - the node's name
   */
  public void jVarChanged(String varName){
    jEstado.removeAllItems();
    if (bayesianNetwork.getNodo( varName) != null) {
      Vector estVar = bayesianNetwork.getNodo( varName).
         getEstados();
    for (int i = 0; i < estVar.size(); i++) {
       jEstado.addItem( (String) estVar.get(i));
    }
    if (bayesianNetwork.getNodo( varName).hasExperienceTable())
      internalFrame.buttonAdaptation.setEnabled(true);
      else
        internalFrame.buttonAdaptation.setEnabled(false);
  }

  }

  void jVar_itemStateChanged(ItemEvent e) {
     jVarChanged((String)e.getItem());
  }

  /**
   * Propagate the new evidence
   */
  public void Aceptar() {
    if (jVar.getSelectedItem()!=null && jEstado.getSelectedItem()!=null){
       agregarObservacion( (String) jVar.getSelectedItem(),
                       (String) jEstado.getSelectedItem());
       probLabel.setText( (new Double(getProb()).toString()));
       repaint();
       internalFrame.getNetView().repaint();

    }
  }

  private void agregarObservacion(String var, String estado) {
    bayesianNetwork.getNodo(var).setObservacion(estado);
    String c=existeObservacion(var);
    if (c!=null)
      jObser.removeItem((String) c);
    jObser.addItem(var + "-" + estado);

  }

  private String existeObservacion(String var){

    for (int i=0; i<jObser.getItemCount(); i++){
      if (((String) jObser.getItemAt(i)).startsWith(var))
        return (String) jObser.getItemAt(i);
    }
    return null;
  }

  public void reinicializarRed()  {
    reinicializar();
    this.showForm("obj17.ViewSumNormal");
    infoLabel.setText("Network initialized (All evidence retracted)");
    probLabel.setText("");
    internalFrame.getNetView().repaint();
  }

  public void reinicializar(){
    int cantVar=jObser.getItemCount();
     for (int i = 0; i < cantVar; i++) {
       deleteObser( (String) jObser.getItemAt(0));

     }
  }

  public void deleteObser(String observacion) {
    String var = getVar(observacion);
    if (bayesianNetwork.getNodo(var).estaObservada())
      bayesianNetwork.getNodo(var).delObservacion();
    jObser.removeItem(observacion);
  }


  public void Delete(){
    if (jObser.getSelectedItem() != null)
      deleteObser( (String) jObser.getSelectedItem());
    probLabel.setText((new Double (getProb()).toString()));
    repaint();
    internalFrame.getNetView().repaint();

  }

  private String getVar(String obs) {
    return obs.substring(0, obs.indexOf("-"));
  }

  private String getEstate(String obs) {
    return obs.substring(obs.indexOf("-") + 1, obs.length());
  }

  private double getProb(){
    Component[] gbarras=grafBarras.getComponents();
    double valor=1;
    for (int i=0;i<gbarras.length;i++){
      valor=valor*((BarViewNodo)gbarras[i]).getProb();
    }
    return valor;
  }

public void setText(String text){
   infoLabel.setText(text);
}

void this_mousePressed(MouseEvent e) {

   if (e.getComponent()  instanceof View){
     String var = ( (View) e.getComponent()).getTitle();
     String delObs=existeObservacion(var);
     if (delObs!=null)
     jObser.setSelectedItem(delObs);
     Delete();
   }
   else{
     String
dato=((View)e.getComponent().getParent()).getInfo(e.getComponent());
     String var = this.getVar(dato);
     String state = this.getEstate(dato);
     if ( (var != null) && (state != null)) {
       jVar.setSelectedItem(var);
       jEstado.setSelectedItem(state);
       Aceptar();
     }

   }
  }

}


class RunPanel_jVar_itemAdapter implements java.awt.event.ItemListener {
  RunPanel adaptee;

  RunPanel_jVar_itemAdapter(RunPanel adaptee) {
    this.adaptee = adaptee;
  }
  public void itemStateChanged(ItemEvent e) {
    adaptee.jVar_itemStateChanged(e);
  }
}

class RunPanel_bAceptar_actionAdapter implements
java.awt.event.ActionListener {
  RunPanel adaptee;

  RunPanel_bAceptar_actionAdapter(RunPanel adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.Aceptar();
  }

}

class RunPanel_bDelete_actionAdapter implements
java.awt.event.ActionListener {
  RunPanel adaptee;

  RunPanel_bDelete_actionAdapter(RunPanel adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    adaptee.Delete();
  }
}


class RunPanel_this_mouseAdapter extends java.awt.event.MouseAdapter {
RunPanel adaptee;

RunPanel_this_mouseAdapter(RunPanel adaptee) {
  this.adaptee = adaptee;
}

public void mousePressed(MouseEvent e) {
  adaptee.this_mousePressed(e);
}
}





